# -*- coding: utf-8 -*-
'''

'''

import sys
import math 
from random import *
from math import atan2, atan, sqrt


'''
	Funcao Recursiva
'''

def frec(l1, x, n):
	'''
	frec - devolve uma lista com x elementos x
	x - o elemento a repetir
	n - numero de repeticoes 
	'''

	if not n:
		return l1
		pass
	else:
		return [x] + frec(l1, x, n -1)
	pass

'''
Recursividade de cauda
'''

def factorial(n):
	if n <= 0:
		return 1
	else:
		return n * factorial(n  - 1)
	pass

def factorial_de_cauda(n):
	def fact(i=n, acc=1):
		if i == 0:
			return acc
		else:
			return fact(i -1,(acc * i))
	return fact()

'''
Geradores
'''

'''
	Funcoes Usadas com Iteradores e Compreensoões de Listas
'''

def gerar_cubos(N):
	for i in range(N):
		yield i ** 3
	pass

def gerar_quad(N):
	for i in range(N):
		yield i ** 2
	pass

def raiz(x, y):
	return math.sqrt(x + y)

def predicado(s):
	return len(s) % 2

def f(x, y):
	return x + math.sqrt(y)

'''
	Expressoes lambda
'''

def f(x):
	if len(x) % 2 -1:
		return x.lower()
	else:
		return x.upper()
	pass

def main():
	l2 = frec([], 'Bu', 5) 
	print l2
	print factorial_de_cauda(5)
	
	'''
	Iteradores
	'''

	lista = ['a', 'b', 'c']
	
	it = iter(lista)
	print it
	x1 = it.next()
	print x1
	x2 = it.next()
	print x2

	lista = ['a', 'b', 'c', 'd', 'f']
	it = iter(lista)
	x = it.next()
	try:
		while it:
			print x
			x = it.next()
		pass
	except StopIteration:
		print "Fim da Lista"
		pass

	'''
	Compreensoões de Listas e Expressoes de Geração
	'''

	lista_linhas = ['        uma','  duas','       tres']
	
	# expressão de geracao - devolve iterador
	it = (linha.strip() for linha in lista_linhas)
	print it.next() + it.next() + it.next()


	total_letras = sum(len(linha.strip())
						for linha in lista_linhas)

	print "total letras {0}".format(total_letras)

	# compreensao de lista -- devolve uma lista
	lista = [linha.strip()
			for linha in lista_linhas
				if len(linha) > 7]

	print lista

	'''
	Geradores
	'''
	
	gen = gerar_cubos(5)
	print gen.next()
	print gen.next()
	print gen.next()
	print gen.next()
	print gen.next()
	print

	for y in gerar_cubos(5):
		print y
		pass

	'''
	Funcoes Usadas com Iteradores e Compreensoões de Listas
	'''
	'''
	lista = map(raiz, gerar_cubos(5), gerar_quad(5))
	i = 0
	while i < 5:
		print i, "->", math.sqrt(i ** 3 + i ** 2), " ==" , lista[i]
		i += 1
		pass

	lista = filter(predicado, ['batata', 'couve','cebola','repolho'])
	print lista
	print reduce(f, gerar_cubos(5))
	'''
	'''
	Expressoes lambda
	'''

	expressao = lambda x: x.lower() if len(x) % 2 - 1 else x.lower()
	lista =['Lisboa', 'Caracas', 'Madrid', 'Londres', 'Berlin', 'Paris'] 
	lista_out1 = map(expressao, lista)
	lista_out2 = map(f, lista)
	print lista_out1
	print lista_out1

	'''
	Conjuntos
	'''

	lista1 = [1, 2, 3, 2, 4, 5, 5, 1, 3]
	lista2 = [x for x in set(lista1)]
	print lista2

	s1 = {'A', 'B', 'C', 'D', 'E'}
	s2 = {'A', 'B'}
	print s1 & s2, s1 ^ s2, s1 | s2
	print s1 < s2, s1 - s2
	print s1.union(s1), s1.intersection(s2)

	'''
	Dicionarios
	'''
	d1 = {'Programacao1' : 15,
		'Programacao1' : 13,
		'Programacao1' : 12,
		'Programacao1' : 17		}

	d1['Algebra'] = 13
	media = 0.0
	c = 0
	for valor in d1.itervalues():
		media += valor
		c += 1
		pass
	media /= c
	print "media =", media

	for  chave, valor in d1.iteritems():
		print chave, valor
		pass

	'''
	Modulos
	'''
	#rint sys.path
	lista = [uniform(0, 100) for k in range(10)]
	
	lista2 = map(lambda x, y: (round(x), round(atan2(x,y) * 180.0 / math.pi)), 
			map(sqrt, lista), 
			map(lambda x : x **0.5, lista))

	for raiz, grau in lista2:
		print "raiz =", raiz, "graus =", grau 
		pass
	
	pass

main()